package com.scmt.hmzd.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.scmt.core.common.exception.ScmtException;
import com.scmt.core.common.utils.ResultUtil;
import com.scmt.core.common.vo.PageVo;
import com.scmt.core.common.vo.Result;
import com.scmt.hmzd.config.WeixinPayConfig;
import com.scmt.hmzd.config.WxConfig;
import com.scmt.hmzd.constants.OrderCacheNames;
import com.scmt.hmzd.entity.*;
import com.scmt.hmzd.enums.OrderEnum;
import com.scmt.hmzd.service.*;
import com.scmt.hmzd.utils.*;
import com.scmt.hmzd.wxLoginUtils.WxSecurityUtil;
import io.swagger.annotations.Api;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yzy
 */
@Api(tags = "移动端后台接口")
@RestController
@RequestMapping("/scmt/appMain")
@Slf4j
public class AppMainController {
    @Autowired
    private WxSecurityUtil securityUtil;
    @Autowired
    private IHmProjectService iHmProjectService;
    @Autowired
    private IHmTechnicianService iHmTechnicianService;
    @Autowired
    private IHmOrderService iHmOrderService;
    @Autowired
    private IHmOrderItemService iHmOrderItemService;

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private IHmWxUserService iHmWxUserService;

    @Autowired
    private IHmUserAddrService iHmUserAddrService;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private IHmDisableDateService iHmDisableDateService;

    @Autowired
    private IHmCommService iHmCommService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IHmCouponUserService iHmCouponUserService;

    @Autowired
    private IHmCouponUseRecordService iHmCouponUseRecordService;

    @Autowired
    private IHmCouponService iHmCouponService;


    /***
     * 项目列表查询接口  分页
     */
    @GetMapping("queryProjectListByPage")
    public Result<Object> queryProjectListByPage(HmProject hmProject, PageVo pageVo) {
        try {
            IPage<HmProject> result = iHmProjectService.queryHmProjectListByPage(hmProject, null, pageVo);
            return ResultUtil.data(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }


    /***
     * 项目详情信息
     */
    @GetMapping("queryProjectDetail")
    public Result<Object> queryProjectDetail(@RequestParam String projectId) {
        try {
            HmProject result = iHmProjectService.getById(projectId);
            return ResultUtil.data(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }


    /***
     * 技师查询列表 分页   需传入经纬度信息
     */
    @GetMapping("queryTechnicianListByPage")
    public Result<Object> queryTechnicianListByPage(HmTechnician technician, PageVo pageVo) {
        try {
            IPage<HmTechnician> result = iHmTechnicianService.queryTechnicianListByPage(technician, pageVo);
            return ResultUtil.data(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }

    /**
     * 查询技师的评论
     *
     * @param technicianId
     * @return
     */
    @GetMapping("queryTechnicianComm")
    public Result<Object> queryTechnicianComm(@RequestParam String technicianId) {
        try {
            QueryWrapper<HmComm> hmCommQueryWrapper = new QueryWrapper<>();
            hmCommQueryWrapper.eq("technician_id", technicianId);
            hmCommQueryWrapper.eq("status", 1);
            List<HmComm> commList = iHmCommService.list(hmCommQueryWrapper);

            String[] commArr = new String[]{"很好，技术不错", "手法舒服", "技术可以", "服务好，态度好", "很好，服务不错"};
            Random random = new Random();
            if(commList == null || commList.size() < 5) {
                if(commList == null) {
                    commList = new ArrayList<>();
                }
                for (int i = 0; i < 5; i++) {
                    HmComm hmComm = new HmComm();
                    hmComm.setCreateTime(new Date());
                    hmComm.setTechnicianId(technicianId);
                    hmComm.setContent(commArr[random.nextInt(4)]);
                    hmComm.setAnonymous(1);
                    hmComm.setTechnicalScore(5);
                    hmComm.setServiceScore(5);
                    commList.add(hmComm);
                }
            }
            return ResultUtil.data(commList);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }


    /**
     * 查询个人订单信息
     */
    @GetMapping("queryOrderListDataByPage")
    public Result<Object> queryOrderListDataByPage(HmOrder hmOrder, PageVo pageVo) {
        try {
            hmOrder.setUserId(securityUtil.getCurrentWxUser().getId());
            IPage<HmOrder> result = iHmOrderService.queryOrderListDataByPage(hmOrder, pageVo);
            return ResultUtil.data(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }

    /**
     * 订单详情
     *
     * @param orderId
     * @return
     */
    @GetMapping("queryOrderDetailData")
    public Result<Object> queryOrderDetailData(@RequestParam(required = true) String orderId) {
        try {
            HmOrder byId = iHmOrderService.getById(orderId);
            if (byId == null) {
                return ResultUtil.error("订单不存在！");
            }
            byId.setHmProject(iHmProjectService.getById(byId.getProjectId()));
            byId.setUserAddr(iHmUserAddrService.getById(byId.getAddrOrderId()));
            byId.setTechnician(iHmTechnicianService.getById(byId.getTechnicianId()));
//            QueryWrapper<HmOrderItem> hmOrderItemQueryWrapper = new QueryWrapper<>();
//            hmOrderItemQueryWrapper.eq("order_id", byId.getId());
//            byId.setOrderItemList(iHmOrderItemService.list(hmOrderItemQueryWrapper));
            return ResultUtil.data(byId);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error("查询异常:" + e.getMessage());
        }
    }

    /**
     * 保存订单信息
     *
     * @param hmOrder
     * @return
     */
    @PostMapping("saveOrderInfo")
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> saveOrderInfo(@RequestBody HmOrder hmOrder) {
        try {
            String userId = securityUtil.getCurrentWxUser().getId();
            // 防止重复、同时提交
            boolean cad = RedisUtil.cad(OrderCacheNames.ORDER_CONFIRM_UUID_KEY + OrderCacheNames.UNION + userId, userId);
            if (cad) {
                return ResultUtil.error("禁止重复提交订单！");
            }

            if (hmOrder.getServiceTime() == null) {
                return ResultUtil.error("服务时间不能为空！");
            }

            HmProject hmProject = iHmProjectService.getById(hmOrder.getProjectId());
//            List<HmOrderItem> orderItemList = hmOrder.getOrderItemList();
//            Double price = 0.0;
//            int timeLong = 0;
//            String projectName = "";
//            for (HmOrderItem hmOrderItem : orderItemList) {
//                price += hmOrderItem.getPrice().doubleValue() * hmOrderItem.getProjectCount();
//                timeLong += hmOrderItem.getTimeLong();
//                projectName += "," + hmOrderItem.getProjectName();
//            }

            HmUserAddr userAddr = iHmUserAddrService.getById(hmOrder.getAddrOrderId());
            // 使用雪花算法生成的订单号
            String orderNumber = String.valueOf(snowflake.nextId());
            hmOrder.setOrderNum(orderNumber);
            BigDecimal carMoney = hmOrder.getCarMoney();
            BigDecimal price = hmProject.getPrice();
            BigDecimal orderPrice = price.add(carMoney);
            hmOrder.setOrderPrice(orderPrice);
            hmOrder.setTimeLong(hmProject.getTimeLong());
            hmOrder.setProjectName(hmProject.getTitle());
            hmOrder.setStatus(OrderEnum.ORDER_DEFAULT.getIndex());
            hmOrder.setIsUp(0);
            hmOrder.setDelFlag(0);
            hmOrder.setIsComment(0);
            hmOrder.setReceiverName(userAddr.getReceiver());
            hmOrder.setReceiverMobile(userAddr.getMobile());
            hmOrder.setCreateTime(new Date());
            hmOrder.setIsSettled(0);
            hmOrder.setUserId(userId);

            HmTechnician technician = iHmTechnicianService.getById(hmOrder.getTechnicianId());
            hmOrder.setTechnicianName(technician.getName());

            hmOrder.setLat(technician.getLat());
            hmOrder.setLng(technician.getLng());

            QueryWrapper<HmWxUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(HmWxUser::getId, technician.getWxUserId());
            queryWrapper.orderByDesc("create_time");
            queryWrapper.last("LIMIT 1");
            HmWxUser one = iHmWxUserService.getOne(queryWrapper);
            hmOrder.setOpenid(one.getOpenid());
            HmCoupon hmCoupon = iHmCouponService.getById(hmOrder.getCouponId());
            if (hmCoupon != null) {
                hmOrder.setDiscountPrice(hmCoupon.getReduceAmount());
            }

            boolean save = iHmOrderService.save(hmOrder); //保存订单信息
            if (save) {
//                orderItemList.forEach(item -> {
//                    item.setOrderId(hmOrder.getId());
//                    item.setOrderNum(orderNumber);
//                    item.setDelFlag(0);
//                });
//                iHmOrderItemService.saveBatch(orderItemList); //保存订单子项信息
                //根据预约时间  计算出当前技师不可预约的时间  并存入表中
                Date serviceTime = hmOrder.getServiceTime();
                Calendar instance = Calendar.getInstance();
                instance.setTime(serviceTime);
                instance.add(Calendar.MINUTE, hmProject.getTimeLong());

                SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
                SimpleDateFormat hhmm = new SimpleDateFormat("HH:mm");


                int count = (int) Math.ceil((double) hmProject.getTimeLong() / 30);
                System.out.println("count=====" + count);

                ArrayList<HmDisableDate> dateArrayList = new ArrayList<>();

                instance.setTime(serviceTime); //设置预约的服务时间   向上取整
                for (int i = 1; i <= count; i++) {
                    instance.add(Calendar.MINUTE, 30);//添加30分钟
                    Date time = instance.getTime();
                    String format = yyyyMMdd.format(time);
                    String format1 = hhmm.format(time);
                    System.out.println("增加日期：===" + format);
                    System.out.println("增加小时分钟：===" + format1);

                    HmDisableDate hmDisableDate = new HmDisableDate();
                    hmDisableDate.setDisableDate(time);
                    hmDisableDate.setDisableTime(format1);
                    hmDisableDate.setTechnicianId(hmOrder.getTechnicianId());
                    dateArrayList.add(hmDisableDate);
                }

                instance.setTime(serviceTime); //设置预约的服务时间   向下判断，这里暂时设置和往后的时间一样， 后面订规则
                for (int i = 1; i <= count; i++) {
                    instance.add(Calendar.MINUTE, -30);//添加30分钟
                    Date time = instance.getTime();
                    String format1 = hhmm.format(time);

                    HmDisableDate hmDisableDate = new HmDisableDate();
                    hmDisableDate.setDisableDate(time);
                    hmDisableDate.setDisableTime(format1);
                    hmDisableDate.setTechnicianId(hmOrder.getTechnicianId());
                    dateArrayList.add(hmDisableDate);
                }
                HmDisableDate hmDisableDate = new HmDisableDate();
                hmDisableDate.setDisableDate(yyyyMMdd.parse(yyyyMMdd.format(serviceTime)));
                hmDisableDate.setDisableTime(hhmm.format(serviceTime));
                hmDisableDate.setTechnicianId(hmOrder.getTechnicianId());
                dateArrayList.add(hmDisableDate);

                iHmDisableDateService.saveBatch(dateArrayList);


                //如果使用了优惠券，把优惠券的状态置为已使用并添加使用记录
                if (StringUtils.isNotBlank(hmOrder.getCouponId()) && hmCoupon != null) {
                    QueryWrapper<HmCouponUser> hmCouponUserQueryWrapper = new QueryWrapper<>();
                    hmCouponUserQueryWrapper.lambda().eq(HmCouponUser::getUserId, userId);
                    hmCouponUserQueryWrapper.lambda().eq(HmCouponUser::getCouponId, hmOrder.getCouponId());
                    hmCouponUserQueryWrapper.lambda().eq(HmCouponUser::getStatus, 1);
                    HmCouponUser serviceOne = iHmCouponUserService.getOne(hmCouponUserQueryWrapper);
                    if (serviceOne != null) {
                        HmCouponUser couponUserUpdate = new HmCouponUser();
                        couponUserUpdate.setStatus(2);
                        couponUserUpdate.setCouponUserId(serviceOne.getCouponUserId());
                        iHmCouponUserService.updateById(couponUserUpdate);

                        HmCouponUseRecord hmCouponUseRecord = new HmCouponUseRecord();
                        hmCouponUseRecord.setCouponUserId(serviceOne.getCouponUserId());
                        hmCouponUseRecord.setUserId(userId);
                        hmCouponUseRecord.setStatus(2);
                        hmCouponUseRecord.setAmount(hmCoupon.getReduceAmount());
                        hmCouponUseRecord.setOrderNumber(orderNumber);
                        hmCouponUseRecord.setUseTime(new Date());
                        iHmCouponUseRecordService.save(hmCouponUseRecord);
                    }
                }
                // 防止重复提交
                stringRedisTemplate.opsForValue().set(OrderCacheNames.ORDER_CONFIRM_UUID_KEY + OrderCacheNames.UNION + userId, hmOrder.getId());
                return ResultUtil.data(hmOrder.getId());
            }
            throw new ScmtException("下单异常");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
            return ResultUtil.error("下单异常！" + e.getMessage());
        }
    }


    /**
     * 保存技师的评论信息
     *
     * @return
     */
    @PostMapping("saveComm")
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> saveComm(@RequestBody HmComm hmComm) {
        hmComm.setCreateTime(new Date());
        hmComm.setStatus(1);//先默认显示
        boolean save = iHmCommService.save(hmComm);
        if (save) {
            //如果回复成功，需要调用公众号接口，给当前技师发送红包

            //调用发送红包成功后  需要修改订单的状态
            HmOrder hmOrder = new HmOrder();
            hmOrder.setId(hmComm.getOrderId());
            hmOrder.setStatus(OrderEnum.ORDER_COMMON.getIndex());
            iHmOrderService.updateById(hmOrder);
            //重新结算当前技师的评分
            return ResultUtil.data("评论保存成功！");
        }
        throw new ScmtException("评论保存失败！");
    }


    /**
     * 客户手动点击提前结束订单
     *
     * @return
     */
    @GetMapping("settlementOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> settlementOrder(@RequestParam String orderId) {
        try {
            //用户提前结束订单的，修改订单状态，并支付红包给技师
            HmOrder hmOrder = iHmOrderService.getById(orderId);
            if (hmOrder == null) {
                return ResultUtil.error("订单不存在！");
            }
            HmOrder updateOrder = new HmOrder();
//            //支付红包
//            boolean result = wxConfig.sendRedpack(hmOrder.getOpenid(), hmOrder.getOrderPrice().doubleValue());
//            if (result) {
//                updateOrder.setIsSettled(1);
//                hmOrder.setSettledTime(new Date());
//            }
            updateOrder.setId(hmOrder.getId());
            updateOrder.setStatus(OrderEnum.ORDER_STOP.getIndex());
            updateOrder.setEndTime(new Date());
            boolean b = iHmOrderService.updateById(updateOrder);
            if(b) {
                return ResultUtil.data("订单结束成功！");
            }
            return ResultUtil.error("订单结束失败！");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
            throw new ScmtException("结束订单失败！");
        }
    }


    @GetMapping("deleteOrder")
    public Result<Object> deleteOrder(@RequestParam String orderId) {
        HmOrder updateOrder = new HmOrder();
        updateOrder.setId(orderId);
        boolean b = iHmOrderService.removeById(updateOrder);
        if (b) {
            return ResultUtil.data("删除成功！");
        }
        throw new ScmtException("订单删除失败！");
    }


    /**
     * 需在用户升级支付后调用
     * 技师未接单时，可以升级项目  就是在当前订单基础上，把订单子项修改一下
     *
     * @return
     */
    @GetMapping("upgradeProjectOrder")
    public Result<Object> upgradeProjectOrder(@RequestParam String orderId, @RequestParam String newProjectId, HttpServletRequest request) throws IOException {
        HmOrder hmOrder = iHmOrderService.getById(orderId);
        if (hmOrder == null) {
            return ResultUtil.error("订单异常，无法升级项目！");
        }
        if (!Objects.equals(hmOrder.getStatus(), OrderEnum.ORDER_PAY.getIndex())) {
            return ResultUtil.error("技师已接单，不能升级项目！");
        }
        HmWxUser currentWxUser = securityUtil.getCurrentWxUser();
        if (currentWxUser == null) {
            return ResultUtil.error("用户不明确！无法升级项目！");
        }

        HmProject newProject = iHmProjectService.getById(newProjectId);
        double price = newProject.getPrice().doubleValue() - hmOrder.getOrderPrice().doubleValue();//计算升级项目需要支付的金额
        // 使用雪花算法生成的订单号
        String orderNumber = String.valueOf(snowflake.nextId());
        HmOrder updateOrder = new HmOrder();
        updateOrder.setId(orderId);
        updateOrder.setOrderNum(orderNumber);
        iHmOrderService.updateById(updateOrder);

        WxUtils wxUtils = new WxUtils();
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("appid", WeixinPayConfig.appid);//微信支付分配的公众账号ID(企业corpid即为此appId)
        data.put("mch_id", WeixinPayConfig.mch_id);
        data.put("nonce_str", wxUtils.getRandomString(32)); // 通过微信工具类生成 随机字符串"会员充值”);
        data.put("body", "项目服务费用");  // 商品描述xx
        data.put("out_trade_no", orderNumber); //订单号 唯一  升级项目的，用订单号作为微信订单号
        data.put("total_fee", Long.parseLong(AmountUtil.convertDollar2Cent(String.valueOf(price)))); // 标价金额
//        data.put("total_fee", 1); //测试金额1分
        data.put("spbill_create_ip", wxUtils.getIpAddr(request));  // 终端IP
        data.put("openid", currentWxUser.getOpenid());  // 公众号用户的openid
        data.put("notify_url", "https://jcepay.lzjczl.com/hmzdApi/scmt/appMain/upProjectPayResult");//支付回调通知地址  专门用于接收升级项目的
        data.put("trade_type", "JSAPI"); //交易类型
        data.put("attach", newProjectId);
        data.put("sign", WxConfig.getSign(data));
        String xml = XmlUtil.genXml(data);
        HttpResponse httpResponse = HttpClientUtil.sendXMLDataByPost(WeixinPayConfig.url, xml);
        HttpEntity entity = httpResponse.getEntity();
        InputStream content = entity.getContent();
        Map<String, Object> elementValueToMap = wxUtils.getElementValueToMap(content);
        log.info("项目升级支付预下单： {}", elementValueToMap);
        if (StringUtil.equals("SUCCESS", elementValueToMap.get("result_code").toString())) {
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("appId", elementValueToMap.get("appid"));
            resultMap.put("timeStamp", String.valueOf(System.currentTimeMillis()));
            resultMap.put("nonceStr", wxUtils.getRandomString(32));
            resultMap.put("package", "prepay_id=" + elementValueToMap.get("prepay_id"));
            resultMap.put("signType", "MD5");
            resultMap.put("paySign", WxConfig.getSign(resultMap));
            return ResultUtil.data(resultMap);
        }
        return ResultUtil.error("项目升级失败！");
    }

    /**
     * 查询当前技师禁用的时间
     *
     * @return
     */
    @GetMapping("getDisableDateByTechnicianId")
    public Result<Object> getDisableDateByTechnicianId(@RequestParam String technicianId, @RequestParam String date) {
        QueryWrapper<HmDisableDate> hmDisableDateQueryWrapper = new QueryWrapper<>();
        hmDisableDateQueryWrapper.lambda().eq(HmDisableDate::getTechnicianId, technicianId);
        hmDisableDateQueryWrapper.lambda().eq(HmDisableDate::getDisableDate, date);
        List<HmDisableDate> list = iHmDisableDateService.list(hmDisableDateQueryWrapper);
        return ResultUtil.data(list);
    }

}
